/*
    Copyright 2007-2011 Patrik Jonsson, sunrise@familjenjonsson.org

    This file is part of Sunrise.

    Sunrise is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.

    Sunrise is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Sunrise.  If not, see <http://www.gnu.org/licenses/>.

*/

/** \file 

    Definition of the DEBUG macro for conditional debug statements of
    different levels, and the ASSERT_ALL macro that asserts something
    for all elements in an array and if fail prints out the failing
    element. */

// $Id$

#ifndef __mcrx_debug__
#define __mcrx_debug__

#include "boost/static_assert.hpp"
#include "blitz/array.h"

#ifdef MCRX_DEBUG_LEVEL
#define DEBUG(level, statement)     \
    if(MCRX_DEBUG_LEVEL>=level) {   \
      statement;                    \
      }
#else
#define DEBUG(level, statement)
#endif

template<typename T> class booltester { BOOST_STATIC_ASSERT(sizeof(T)==0);};
template<> class booltester<bool> {};

template<typename T>
bool xassert_all(T expr)
{
  booltester<T> b;

  return expr;
}

template<typename T>
bool xassert_all(const blitz::_bz_ArrayExpr<T>& expr)
{
  blitz::Array<typename blitz::_bz_ArrayExpr<T>::T_numtype, blitz::_bz_ArrayExpr<T>::rank_> arr(expr);
  for(int i=0; i< arr.size(); ++i)
    if(!arr.data()[i]) {
      std::cerr << "ASSERT_ALL failure at element " << i << "/" << arr.size() << std::endl;
      return false;
    }
  return true;
};


#ifndef NDEBUG
#define ASSERT_ALL(expression) if(!all(expression)) assert(xassert_all(expression));
#else
#define ASSERT_ALL(expression)
#endif

#endif
